// 文件名：span_sensor_window.cpp
// 目的：以 std::span 传递只读滑动窗口，计算移动平均（moving average）。
// 实现：
//   - movingAverage(std::span<const double>)：对当前窗口求和/求平均，空窗口返回 0.0；
//   - 主循环维护固定窗口：
//       * 若已满，则将 [1..end) 前移到 [0..end-1)，在末尾写入新样本；
//       * 未满则直接 push_back；
//   - 每次更新后，以 span 视图包装 buffer 并计算平均。
// 复杂度：
//   - 当前实现每次滑动 O(W)（因为 move 前移）；若追求更高效可用环形缓冲 O(1) 滑动 + 维护滚动和；
//   - 计算平均 O(W)。
// 注意：
//   - std::span 提供零拷贝只读视图，buffer 的生命周期需覆盖 span 的使用期。

#include <algorithm>
#include <iostream>
#include <numeric>
#include <span>
#include <vector>

double movingAverage(std::span<const double> window) {
    if (window.empty()) return 0.0;
    double sum = std::accumulate(window.begin(), window.end(), 0.0);
    return sum / static_cast<double>(window.size());
}

int main() {
    constexpr std::size_t windowSize = 5;
    std::vector<double> incoming{10, 11, 9, 12, 13, 15, 14, 16, 17};

    std::vector<double> buffer;
    buffer.reserve(windowSize);

    for (double sample : incoming) {
        if (buffer.size() == windowSize) {
            // 滑动窗口：把旧元素前移一位，然后写入最新样本
            std::move(buffer.begin() + 1, buffer.end(), buffer.begin());
            buffer.back() = sample;
        } else {
            buffer.push_back(sample);
        }

        std::span<const double> window(buffer);
        std::cout << "latest = " << sample
                  << ", window avg = " << movingAverage(window) << '\n';
    }

    return 0;
}